# Python 包(package)
import math
import time

# 包与普通目录的区别：
# 1. 包是一个目录，包含 __init__.py 文件，该文件可以为空，也可以包含 Python 代码。
# 2. 包可以包含子目录和模块。
# 3. 包可以被导入，可以从包中导入模块。
# 4. 包的导入路径与模块的导入路径不同。

# 导入包
# 1. 导入包的语法：import 包名
# 2. 导入包中的模块的语法：from 包名 import 模块名

# 包的层次结构
# 1. 包可以包含子目录，子目录可以包含子目录，以此类推。
# 2. 包的层次结构决定了模块的导入路径。
# 3. 导入包时，Python 解释器会按照包的层次结构查找模块。

# 包的作用
# 1. 组织代码，便于维护和管理。
# 2. 提高代码的可重用性。
# 3. 避免命名冲突。

import sound.effects.echo as echo
import sound.formats.wavread as wav
import sound.filters.equalizer as equalizer
echo.play()
wav.play()
equalizer.play()


# __init__.py 文件
# 1. __init__.py 文件可以为空，也可以包含 Python 代码，本身也是一个模块。
# 2. __init__.py 文件的作用：
#    a. 让 Python 解释器认识到这个目录是一个包。
#    b. 让 Python 解释器能够找到包中的模块, 使用__all__ 变量可以指定要导入的模块。
# 3. __init__.py 文件可以包含包的文档字符串。
# 4. __init__.py 文件可以执行包的初始化代码。


# 导入sound包中的所有模块
from sound import *
# 如果没有在sound包的__init__.py文件中指定__all__变量可以导入的模块，则下面引用会报错。
print(module_a.name)
print(module_b.name)


# 高频被使用的模块导入
# 可以把常用的模块放到包的__init__.py文件中，这样可以避免在每个模块中重复导入。
# 导入包时，Python 解释器会首先执行 __init__.py 文件里的内容，然后再导入包中的模块。
print(time.time())
print(math.pi)